package com.aracky.system.service.impl;

import com.aracky.common.constants.LoginConstants;
import com.aracky.common.util.ComUtil;
import com.aracky.common.vo.PageVO;
import com.aracky.system.constants.ComConstants;
import com.aracky.system.mapper.SysUserMapper;
import com.aracky.system.mapper.SysUserRoleMapper;
import com.aracky.system.model.entity.SysUser;
import com.aracky.system.model.entity.SysUserRole;
import com.aracky.system.model.request.SysUserRequest;
import com.aracky.system.model.vo.SysUserVO;
import com.aracky.system.service.SysRoleService;
import com.aracky.system.service.SysUserRoleService;
import com.aracky.system.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author zzp
 * @since 2022-07-14 11:22:57
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private Executor asyncTaskExecutor;

    /**
     * 用户新增
     *
     * @param sysUser
     * @return
     */
    @Override
    public boolean save(SysUser sysUser) {
        int result = sysUserMapper.insert(sysUser);       //存储返回结果
        return result > 0 ? true : false;
    }

    /**
     * 用户修改
     *
     * @param
     * @return
     */
    @Override
    public int update(SysUser sysUser) {
        int result = sysUserMapper.updateById(sysUser);   //存储返回结果
        return result;
    }

    /**
     * 删除用户
     *
     * @param userId
     * @return
     */
    @Override
    public int delete(Long userId) {
        return sysUserMapper.deleteById(userId);
    }

    /**
     * 查询用户详情
     *
     * @param userId
     * @return
     */
    @Override
    public SysUser get(Long userId) {
        return sysUserMapper.selectById(userId);
    }

    /**
     * 查询用户列表
     *
     * @param sysUserRequest
     * @return
     */
    @Override
    public PageVO<SysUserVO> getUserPage(SysUserRequest sysUserRequest) {
        IPage<SysUserVO> page = sysUserMapper.findUser(sysUserRequest.toPage(), sysUserRequest);
        return PageVO.convertPage(page);
    }

    /**
     * 分配角色给用户
     *
     * @param userId
     * @param roleIds
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRole(Long userId, Long[] roleIds) {
        if (roleIds == null || roleIds.length == 0) {
            return;
        }

        //判断数据是否存在
        LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper
                = Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getUserId, userId);
        List<SysUserRole> userRoleList = sysUserRoleService.list(lambdaQueryWrapper);

        List<Long> noExistsIdList = Arrays.asList(roleIds);
        if (userRoleList != null && !userRoleList.isEmpty()) {
            List<Long> dbRoleIdList = userRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
            //取出差集进行新增
            noExistsIdList = noExistsIdList.stream()
                    .filter(item -> !dbRoleIdList.contains(item))
                    .collect(Collectors.toList());
        }

        SysUserRole userRole;
        // 新增用户与角色管理
        List<SysUserRole> list = new ArrayList<SysUserRole>(noExistsIdList.size());
        for (Long roleId : noExistsIdList) {
            userRole = new SysUserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            list.add(userRole);
        }
        sysUserRoleMapper.batchUserRole(list);
    }

    /**
     * 检查邮箱是否唯一
     *
     * @param email
     * @return
     */
    @Override
    public Long getCheckByEmail(String email) {
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper
                = Wrappers.<SysUser>lambdaQuery().eq(SysUser::getEmail, email);
        return sysUserMapper.selectCount(lambdaQueryWrapper);
    }

    /**
     * 检查账号是否唯一
     *
     * @param loginName
     * @return
     */
    @Override
    public Long getCheckLoginName(String loginName) {
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper
                = Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, loginName);
        return sysUserMapper.selectCount(lambdaQueryWrapper);
    }

    /**
     * 检查电话号码是否唯一
     *
     * @param phoneNumber
     * @return
     */
    @Override
    public Long getCheckPhone(String phoneNumber) {
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper
                = Wrappers.<SysUser>lambdaQuery().eq(SysUser::getPhonenumber, phoneNumber);
        return sysUserMapper.selectCount(lambdaQueryWrapper);
    }

    @Override
    public void updateLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginDate(LocalDateTime.now());
        //获取IP
        String hostAddress;
        try {
            hostAddress = Inet4Address.getLocalHost().getHostAddress();
            sysUser.setLoginIp(hostAddress);
        } catch (UnknownHostException e) {
            log.error("获取ip失败：{}" + e.getMessage());
        }
        this.update(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SysUser> saveWxUser(List<SysUser> sysUserList) {
        if (sysUserList == null || sysUserList.isEmpty()) {
            return null;
        }


        String encode = passwordEncoder.encode(LoginConstants.USER.DEFAULT_PASWORD);
        //查询存在微信id的用户
        LambdaQueryWrapper<SysUser> userLambdaQueryWrapper =
                Wrappers.<SysUser>lambdaQuery().isNotNull(SysUser::getWxUserId);
        List<SysUser> dbUserList = this.list(userLambdaQueryWrapper);


        Map<String, Long> dbWxUserMap = dbUserList.stream()
                .collect(Collectors.toMap(SysUser::getWxUserId, SysUser::getUserId, (value1, value2) -> value2));
        //更新
        List<SysUser> updateUserList = new ArrayList<>(sysUserList.size());

        //保存
        List<SysUser> saveUserList = new ArrayList<>(sysUserList.size());

        //默认角色
        Long defaultRoleId = sysRoleService.getDefaultRole(ComConstants.ROLE.ROLE_DEFAULT_EMP);

        List<SysUserRole> userRoleList = new ArrayList<>();


        //求出交集进行更新，并且设置默认角色
        for (SysUser wxUser : sysUserList) {
            boolean pass = dbWxUserMap.containsKey(wxUser.getWxUserId());
            if (pass) {
                wxUser.setUserId(dbWxUserMap.get(wxUser.getWxUserId()));
                userRoleList.add(new SysUserRole(wxUser.getUserId(), defaultRoleId));
                updateUserList.add(wxUser);
                continue;
            }
            wxUser.setPassword(encode);
            saveUserList.add(wxUser);
        }

        if (ComUtil.isNotNullList(saveUserList)) {
            //去重，可能会有员工存在多个部门下，通过部门拉取会有多个
            saveUserList = saveUserList.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                            () -> new TreeSet<>(Comparator.comparing(SysUser::getWxUserId))),
                            ArrayList::new));
            this.saveBatch(saveUserList);

            saveUserList.stream().forEach(user -> {
                userRoleList.add(new SysUserRole(user.getUserId(), defaultRoleId));
            });
        }

        if (ComUtil.isNotNullList(updateUserList)) {
            this.updateBatchById(updateUserList);
        }

        //需要保存默认角色信息，单独开线程处理
        CompletableFuture.runAsync(() ->
                        sysUserRoleService.saveBatchUserRole(userRoleList),
                asyncTaskExecutor);

        updateUserList.addAll(saveUserList);

        //对数据进行去重
        return updateUserList.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(
                        () -> new TreeSet<>(Comparator.comparing(SysUser::getUserId))),
                        ArrayList::new));
    }


}
